// reWriteWatchPack.js 重写watchPack的编译逻辑
// by gjw 2023.8.8

const fs = require('fs')
const path = require('path')
const Watchpack = require('watchpack')
const updateRoutes = require('./watchComponents')

function setAggregate () {
    this.aggregateTimeout = setTimeout(this._onTimeout, this.options.aggregateTimeout)
}

function adaptAuto (file) {
    const isViews = file.startsWith(path.join(__dirname, 'src/components/views/')) && file.endsWith('.vue')
    const isAutoRoutes = file === path.join(__dirname, 'src/router/autoRoutes.ts') && fs.statSync(file).isFile()
    if (!this.cacheModule) {
        this.cacheModule = []
    }
    if (this.cacheModule.length || isViews || isAutoRoutes) {
        this.res = updateRoutes('latest')
        const isSame = this.res.compare(global.latestRoutes, this.res.latest)
        if (isViews) {
            if (isSame) {
                if (!this.cacheModule.length || !this.cacheModule.includes('views')) {
                    setAggregate.call(this)
                }
            } else {
                this.cacheModule.push('views')
                if (this.cacheModule.includes('auto')) {
                    setAggregate.call(this)
                }
            }
        } else if (isAutoRoutes) {
            // 因为webpack对新增文件存在不响应，这里autoRoutes单独变化时统一全部立即响应
            // webpack在初始run之后马上删除文件夹无法正确编译，这里存在bug，临时解决办法为：手动随便保存一下任何文件（不需要修改内容）
            this.cacheModule.push('auto')
            setAggregate.call(this)
            // if (!isSame) {
            //     this.cacheModule.push('auto')
            //     // console.log(this.cacheModule)
            //     // if (this.cacheModule.includes('views')) {
            //     //     setAggregate.call(this)
            //     // }
            // } else {
                
            // }
        }
    } else {
        setAggregate.call(this)
    }
}

module.exports = function () {
    Watchpack.prototype._onChange = function _onChange (item, mtime, file) {
        file = file || item
        this.mtimes[file] = mtime
        if(this.paused) return
        this.emit('change', file, mtime)
        if(this.aggregateTimeout) { clearTimeout(this.aggregateTimeout) }
        if(this.aggregatedChanges.indexOf(item) < 0) { this.aggregatedChanges.push(item) }
        adaptAuto.call(this, file)
    }
    
    Watchpack.prototype._onRemove = function _onRemove (item, file) {
        file = file || item
        delete this.mtimes[item] 
        if(this.paused) return
        this.emit('remove', item)
        if(this.aggregateTimeout) { clearTimeout(this.aggregateTimeout) }
        if(this.aggregatedRemovals.indexOf(item) < 0) { this.aggregatedRemovals.push(item) }
        adaptAuto.call(this, file)
    }

    Watchpack.prototype._onTimeout = function _onTimeout () {
        this.aggregateTimeout = 0
        this.cacheModule = []
        if (this.res) {
            global.latestRoutes = this.res.latest
        }
        let changes = this.aggregatedChanges
        let removals = this.aggregatedRemovals
        this.aggregatedChanges = []
        this.aggregatedRemovals = []
        this.emit('aggregated', changes, removals)
    }
}
